/*
 * Copyright (C) 2012 Tomas Shestakov. <http://code.google.com/p/jmmo/>
 */

package jmmo.engine.multifacetedactor

import akka.testkit.{ImplicitSender, TestKit}
import org.scalatest.{BeforeAndAfterAll, WordSpec}
import akka.event.EventStream
import akka.actor.{Props, ActorSystem}

/**
 * Tests actor abilities to subscribe and unsubscribe to [[akka.event.EventStream]].
 * @author Tomas Shestakov
 * @param system actor system for testing
 * @param creator a function which returns new instance of [[jmmo.engine.multifacetedactor.MultifacetedActor]]
 */
class ActorSubscriberSpec(system: ActorSystem, creator: => MultifacetedActor with ActorSubscriber, shutdown: Boolean = false)
                                    extends TestKit(system) with ImplicitSender with WordSpec with BeforeAndAfterAll {

  def this() = this(ActorSystem("TestSpec"), new MultifacetedActor with ActorSubscriber {}, true)

  override def afterAll {
    if (shutdown) system.shutdown()
  }

  //send an Event to system.eventStream
  val postEventRole = new ActorRole {
    def id = 'postEventRole
    def receive = {
      case event: EventStream#Event  => {
        context.system.eventStream.publish(event)
      }
    }
  }

  val subscriber = system.actorOf(Props({
    val newActor = creator
    newActor.addRole(postEventRole)
    newActor
  }))

  override val nestedSuites = {
    List(new MultifacetedActorSpec(system, creator))
  }

  "A ActorSubscriber" should {

    "fit MultifacetedActorSpec" in {}

    "send no reply to `AnyRef` message if sender not subscribed at all" in {
      subscriber ! "hello!"
      expectNoMsg()
      subscriber ! None
      expectNoMsg()
    }

    "send reply to String message if sender is subscribed to String Class" in {
      subscriber ! SubscribeRequest(classOf[String])
      subscriber ! "Hello!"
      expectMsg("Hello!")
    }

    "send no reply to `Option` message if sender not subscribed to this class of events" in {
      subscriber ! None
      expectNoMsg()
    }

    "send reply to String message if sender is unsubscribed from any but not String Class" in {
      subscriber ! SubscribeRequest(classOf[Option[Any]])
      subscriber ! "Bye!"
      expectMsg("Bye!")
    }

    "send no reply to String message if sender is unsubscribed from String Class" in {
      subscriber ! UnsubscribeRequest(classOf[String])
      subscriber ! "Bye!"
      expectNoMsg()
   }
  }

}
